#include "ast_tester.h"

void ast_tst_write_src(FILE* dest_src, AST* node)
{
    if (node) {
        switch(node->type)
        {
            case AST_ADD:
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, " + ");
                ast_tst_write_src(dest_src, node->sons[1]);
                break;
            case AST_SUB:
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, " - ");
                ast_tst_write_src(dest_src, node->sons[1]);
                break;
            case AST_MUL:
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, " * ");
                ast_tst_write_src(dest_src, node->sons[1]);
                break;
            case AST_DIV:
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, " / ");
                ast_tst_write_src(dest_src, node->sons[1]);
                break;
            case AST_LIT_INT:
                fprintf(dest_src, "%s", node->symbol[0]->data->lexeme);
                break;
            case AST_LIT_CHAR:
                fprintf(dest_src, "%s", node->symbol[0]->data->lexeme);
                break;
            case AST_IDENTIFIER:
                fprintf(dest_src, "%s", node->symbol[0]->data->lexeme);
                break;
            case AST_ASS:
                fprintf(dest_src, "%s = ", node->symbol[0]->data->lexeme);
                ast_tst_write_src(dest_src, node->sons[0]);
                break;
            case AST_LCMD:
                ast_tst_write_src(dest_src, node->sons[0]);
                if (node->sons[1]) {
                    fprintf(dest_src, ";\n");
                    ast_tst_write_src(dest_src, node->sons[1]);
                }
                break;
            case AST_IF:
                fprintf(dest_src, "if (");
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, ") then ");
                ast_tst_write_src(dest_src, node->sons[1]);
                break;
            case AST_IF_ELSE:
                fprintf(dest_src, "if (");
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, ") then ");
                ast_tst_write_src(dest_src, node->sons[1]);
                fprintf(dest_src, " else ");
                ast_tst_write_src(dest_src, node->sons[2]);
                break;
            case AST_WHILE:
                fprintf(dest_src, "while(");
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, ") ");
                ast_tst_write_src(dest_src, node->sons[1]);
                break;
            case AST_PRINT_STRING:
                fprintf(dest_src, "print \"%s\"", node->symbol[0]->data->lexeme);
                break;
            case AST_RETURN:
                fprintf(dest_src, "return ");
                ast_tst_write_src(dest_src, node->sons[0]);
                break;
            case AST_READ:
                fprintf(dest_src, "read %s", node->symbol[0]->data->lexeme);
                break;
            case AST_OPERATOR_OR:
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, " || ");
                ast_tst_write_src(dest_src, node->sons[1]);
                break;
            case AST_OPERATOR_AND:
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, " && ");
                ast_tst_write_src(dest_src, node->sons[1]);
                break;
            case AST_OPERATOR_L:
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, " < ");
                ast_tst_write_src(dest_src, node->sons[1]);
                break;
            case AST_OPERATOR_LE:
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, " <= ");
                ast_tst_write_src(dest_src, node->sons[1]);
                break;
            case AST_OPERATOR_G:
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, " > ");
                ast_tst_write_src(dest_src, node->sons[1]);
                break;
            case AST_OPERATOR_GE:
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, " >= ");
                ast_tst_write_src(dest_src, node->sons[1]);
                break;
            case AST_OPERATOR_EQ:
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, " == ");
                ast_tst_write_src(dest_src, node->sons[1]);
                break;
            case AST_OPERATOR_NE:
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, " != ");
                ast_tst_write_src(dest_src, node->sons[1]);
                break;
            case AST_OPERATOR_NOT:
                fprintf(dest_src, "!");
                ast_tst_write_src(dest_src, node->sons[0]);
                break;
            case AST_ASS_VEC:
                fprintf(dest_src, "%s[", node->symbol[0]->data->lexeme);
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, "] = ");
                ast_tst_write_src(dest_src, node->sons[1]);
                break;
            case AST_CMD_BLOCK:
                fprintf(dest_src, "\n{\n");
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, "\n}");
                break;
            case AST_FUNC_CALL:
                fprintf(dest_src, "%s(", node->symbol[0]->data->lexeme);
                if (node->sons[0]) {
                    ast_tst_write_src(dest_src, node->sons[0]);
                }
                fprintf(dest_src, ")");
                break;
            case AST_PARAM_LIST:
                ast_tst_write_src(dest_src, node->sons[0]);
                if (node->sons[1]) {
                    fprintf(dest_src, " ");
                    ast_tst_write_src(dest_src, node->sons[1]);
                }
                break;
            case AST_PARAM:
                 ast_tst_write_src(dest_src, node->sons[0]);
                 fprintf(dest_src, " %s", node->symbol[0]->data->lexeme);
                 break;
            case AST_VAR_DEF:
               ast_tst_write_src(dest_src, node->sons[0]);
               fprintf(dest_src, " %s;", node->symbol[0]->data->lexeme);
               break;
            case AST_VEC_DEF:
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, " %s[%s];", node->symbol[0]->data->lexeme, node->symbol[1]->data->lexeme);
                break;
            case AST_FUNC_DEF:
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, " %s(", node->symbol[0]->data->lexeme);
                ast_tst_write_src(dest_src, node->sons[1]);
                fprintf(dest_src, ") ");
                ast_tst_write_src(dest_src, node->sons[2]);
                break;
            case AST_BYTE_TYPE:
                fprintf(dest_src, "byte");
                break;
            case AST_INT_TYPE:
                fprintf(dest_src, "int");
                break;
            case AST_FUNC_PARAM_LIST:
                ast_tst_write_src(dest_src, node->sons[0]);

                if (node->sons[1]) {
                    fprintf(dest_src, ", ");
                    ast_tst_write_src(dest_src, node->sons[1]);
                }
                break;
            case AST_PRINT_EXPR:
                fprintf(dest_src, "print ");
                ast_tst_write_src(dest_src, node->sons[0]);
                break;
            case AST_DEFS:
                ast_tst_write_src(dest_src, node->sons[0]);
                if (node->sons[1]) {
                    fprintf(dest_src, "\n");
                    ast_tst_write_src(dest_src, node->sons[1]);
                }
                break;
            case AST_EXPR_PAR:
                fprintf(dest_src, "(");
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, ")");
                break;
            case AST_VEC_REF:
                fprintf(dest_src, "%s[", node->symbol[0]->data->lexeme);
                ast_tst_write_src(dest_src, node->sons[0]);
                fprintf(dest_src, "]");
                break;
            default:
                printf("Error! unknow node type!\n");
                exit(1);
        }
    }
    
}